﻿using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using StackExchange.Redis;

namespace OA.Infrastructure.Authentication.Redis;

internal class RedisClient
{
    private readonly ConnectionMultiplexer _multiplexer;
    private readonly RedisOptions _options;
    private readonly IDatabase _store;

    public RedisClient(IOptions<RedisOptions> options)
    {
        _options = options.Value;
        _multiplexer = ConnectionMultiplexer.Connect(_options.Connection);

        _store = _multiplexer.GetDatabase(_options.DefaultDB);
    }

    public async Task<bool> SetAsync<TValue>(string key, TValue value, DistributedCacheEntryOptions? options = null, CancellationToken cancellationToken = default)
    {
        TimeSpan? expire = null;

        if (options?.AbsoluteExpiration != null)
        {
            var uniTimeStamp = (options.AbsoluteExpiration.Value - DateTimeOffset.UtcNow).TotalSeconds;

            expire = TimeSpan.FromSeconds(uniTimeStamp);
        }
        else if (options?.AbsoluteExpirationRelativeToNow != null)
        {
            var uniTimeStamp = options.AbsoluteExpirationRelativeToNow.Value.TotalSeconds;

            expire = TimeSpan.FromSeconds(uniTimeStamp);
        }

        return await _store.StringSetAsync(key, Serialize(value), expire);
    }

    public async Task<TValue> GetAsync<TValue>(string key)
    {
        var value = await _store.StringGetAsync(key);

        var ov = Deserialize<TValue>(value.ToString());

        return ov;
    }

    public async Task RemoveAsync(string key)
    {
        await _store.StringGetDeleteAsync(key);
    }

    private static string Serialize<TValue>(TValue value)
    {
        var json = JsonConvert.SerializeObject(value, Formatting.Indented);

        return json;
    }

    private static TValue Deserialize<TValue>(string json)
    {
        return JsonConvert.DeserializeObject<TValue>(json);
    }
}